#include "../server.hpp"

void HandleClose(Channel *channel)
{
    DEBUG_LOG("void HandleClose()!!!, close: %d", channel->Fd());
    channel->Remove();  // 无数据可读或者被信号打断或者出错，直接 粗暴 移除监控
    delete channel;
}

void HandleWrite(Channel *channel)
{
    int fd = channel->Fd();
    const char *data = "调用 HandleWrite 给你回复了";
    int ret = send(fd, data, strlen(data), 0);
    if(ret < 0)
    {
        return HandleClose(channel);
    }
    DEBUG_LOG("void HandleWrite()!!!");
}

void HandleRead(Channel *channel)
{
    int fd = channel->Fd();
    char buf[1024] = {0};
    int ret = recv(fd, buf, sizeof(buf), 0);
    DEBUG_LOG("void HandleRead()!!!, buf: %s", buf);
    if(ret <= 0)
    {
        HandleClose(channel);   // 关闭释放
        return;
    }

    HandleWrite(channel);       // 调用写事件回调，对接收的数据进行回复
}

void HandleEvent(EventLoop *loop, Channel *channel, uint64_t id)
{
    // 任意事件发生，刷新 非活跃连接销毁任务
    loop->TimerRefresh(id);
    DEBUG_LOG("HandleEvent, TimerRefresh !!!");
}


void Acceptor(EventLoop *loop, Channel *lst_channel)
{
    int fd = lst_channel->Fd();
    int newfd = accept(fd, NULL, NULL);
    uint64_t timerid = rand() % 10000;

    Channel *newchannel = new Channel(loop, newfd);       // 为新连接创建 Channel
    newchannel->SetReadCallback(std::bind(HandleRead, newchannel));  // 为通信套接字设置 事件回调
    newchannel->SetWriteCallback(std::bind(HandleWrite, newchannel));
    newchannel->SetCloseCallback(std::bind(HandleClose, newchannel));
    newchannel->SetEventCallback(std::bind(HandleEvent, loop, newchannel, timerid));

    // 非活跃连接超时 10s 后释放
    // 这个定时销毁任务，必须在 该连接 启动事件监控之前，因为启动事件监控后，可能立即就有了事件，但那时候超时释放任务还没被添加
    loop->TimerAdd(timerid, 10, std::bind(HandleClose, newchannel));    // 添加 HandleClose 定时任务

    newchannel->EnableRead();   // 启动事件监控
}

void t1()
{
    srand(time(NULL));
    // Poller poller;
    EventLoop loop;
    Socket lst_sock;
    lst_sock.CreateServer(8787);
    Channel channel(&loop, lst_sock.Fd());    // 为 监听套接字 创建一个 Channel 进行事件管理 、添加修改移除
    channel.SetReadCallback(std::bind(Acceptor, &loop, &channel));       // 设置监听套接字的可读监控，这里回调函数需要为 新连接创建 Channel 并添加监控

    channel.EnableRead();   // 监听套接字启动可读事件监控

    while(1)
    {
        loop.Start();
    }
    lst_sock.Close();
}


int main()
{
    t1();

    return 0;
}